package com.zb.websocket.server;

import com.alibaba.fastjson.JSONObject;
import com.baomidou.mybatisplus.core.toolkit.StringUtils;
import com.zb.utils.ZbNumberUtil;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Component;

import javax.validation.constraints.NotNull;
import javax.websocket.*;
import javax.websocket.server.PathParam;
import javax.websocket.server.ServerEndpoint;
import java.io.IOException;
import java.util.List;
import java.util.concurrent.ConcurrentHashMap;

/**
 * 推送进度消息
 * @Author WEN
 * @Date 2023/12/28 0028
 **/
@Component
@ServerEndpoint("/ws/progress/{progressUuid}")
public class ProgressWebSocketServer {
    private static final Logger logger = LoggerFactory.getLogger(ProgressWebSocketServer.class);

    // 在线人数
    private static int onlineCount = 0;

    // 用户存放每个登录的客户端对应的WebSocket对象
    private static ConcurrentHashMap<String, ProgressWebSocketServer> webSocketMap = new ConcurrentHashMap<>();

    // 与某个登录的客户端的会话连接，需要通过它来给登录的客户端发送数据
    private Session session;

    // 接收进度的uuid唯一识别码
    private String progressUuid;

    /**
     * 建立连接调用的方法
     * @param session
     * @param progressUuid
     */
    @OnOpen
    public void onOpen(Session session, @PathParam("progressUuid") String progressUuid) {
        this.session = session;
        this.progressUuid = progressUuid;
        if (webSocketMap.containsKey(progressUuid)) {
            webSocketMap.remove(progressUuid);
            webSocketMap.put(progressUuid, this);
        } else {
            webSocketMap.put(progressUuid, this);
            addOnlineCount();
        }
        logger.info("ProgressWebSocketServer =====>>>>>> 用户登录了，当前在线人数：" + getOnlineCount());
    }

    /**
     * 关闭连接时调用的方法
     */
    @OnClose
    public void onClose() {
        logger.info("ProgressWebSocketServer =====>>>>>> 连接关闭了");
        if (webSocketMap.containsKey(this.progressUuid)) {
            webSocketMap.remove(this.progressUuid);
            subOnlineCount();
        }
        logger.info("当前进度已退出：" + progressUuid + " ，当前未完成进度：" + getOnlineCount());
    }

    /**
     * 出现错误时调用
     */
    @OnError
    public void onError(Session session, Throwable error) {
        logger.info("ProgressWebSocketServer =====>>>>>> 出现错误了，出错用户：" + this.progressUuid + "，出错原因：" + error.getMessage());
    }

    /**
     * 接收客户端发送过来的消息
     * @param message
     * @param session
     */
    @OnMessage
    public void onMessage(String message, Session session) {
        logger.info("ProgressWebSocketServer =====>>>>>> 客户端发送消息过来了，消息内容："+ message);
    }

    /**
     * 实现服务器主动推送消息到客户端
     * @param message
     */
    public void sendMessage(String message) {
        try {
            this.session.getBasicRemote().sendText(message);
        } catch (IOException e) {
            logger.error("ProgressWebSocketServer =====>>>>>> 主动给客户推送消息失败，消息内容：" + message);
        }
    }

    /**
     * 自定义推送消息的方法，方便外部调用
     * @param progressUuid 进度唯一识别码
     * @param end 是否结束
     * @param importFailtDataList 导入失败的数据集合
     * @param message 进度消息
     */
    public static void send(String progressUuid, boolean end, List importFailtDataList, @NotNull String message) {
        send(progressUuid, end, 0, 0, importFailtDataList, message);
    }

    /**
     * 自定义推送消息的方法，方便外部调用
     * @param progressUuid 进度唯一识别码
     * @param end 是否发送完成
     * @param currentProgress 当前进度
     * @param importFailtDataList 导入失败的数据集合
     * @param message 进度消息
     */
    public static void send(String progressUuid, boolean end, double currentProgress, List importFailtDataList, @NotNull String message) {
        send(progressUuid, end, currentProgress,0, importFailtDataList, message);
    }

    /**
     * 自定义推送消息的方法，方便外部调用
     * @param progressUuid 进度唯一识别码
     * @param end 是否发送完成
     * @param currentProgress 当前进度
     * @param totalCount 总条数
     * @param importFailtDataList 导入失败的数据集合
     * @param message 进度消息
     */
    public static void send(String progressUuid, boolean end, double currentProgress, long totalCount, List importFailtDataList, @NotNull String message) {
        synchronized (webSocketMap) {
            if (StringUtils.isBlank(progressUuid) || !webSocketMap.containsKey(progressUuid)) {
                logger.error("当前[" + progressUuid + "]的进度uuid已失效！");
                return;
            }
            JSONObject obj = new JSONObject();
            String progress = currentProgress + "";
            if (currentProgress != 0) {
                progress = ZbNumberUtil.getPercentage(currentProgress);
            }
            obj.put("currentProgress", progress);
            obj.put("totalCount", totalCount);
            obj.put("importFailtDataList", importFailtDataList);
            obj.put("message", message);
            obj.put("end", end); // 是否发送完成
            logger.info("导入失败数据量：{}，当前进度：{}", importFailtDataList.size(), progress);
            webSocketMap.get(progressUuid).sendMessage(obj.toJSONString());
        }
    }

    /**
     * 获取当前在线人数
     * @return
     */
    public static synchronized int getOnlineCount() {
        return onlineCount;
    }

    /**
     * 增加在线人数
     */
    public static synchronized void addOnlineCount() {
        ProgressWebSocketServer.onlineCount++;
    }

    /**
     * 减少在线人数
     */
    public static synchronized void subOnlineCount() {
        ProgressWebSocketServer.onlineCount--;
    }




}
